﻿using BW.WMS.CodeEnum;
using BW.WMS.LC.Dto.Input;
using BW.WMS.Model;
using BW.WMS.RBAC;
using BW.WMS.StockControl_GJH.Dto.Input;
using BW.WMS.StockControl_GJH.Dto.Output;
using BW.WMS.XKY;
using BW.WMS.XKY.DTO.Output;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using static Volo.Abp.Http.MimeTypes;

namespace BW.WMS.StockControl_GJH
{
    public class AllotAppService : ApplicationService, IAllotAppService
    {
        private readonly IRepository<latestAllotModel, Guid> _latestAllotRepository;
        private readonly IRepository<latestAllotSUBModel, Guid> _latestAllotSubRepository;
        private readonly IRepository<Dm_Warehouser,Guid> _warehouserRepository;
        private readonly IRepository<Dm_ItemType,Guid> _itemTypeRepository;
        private readonly IRepository<Dm_Item, Guid> _itemRepository;
        private readonly IRepository<Dm_Unit, Guid> _unitRepository;
        private readonly IRepository<UserModel, Guid> _userRepository;
        private readonly IRepository<Dm_Librarylocation, Guid> _librarylocationRepository;
        private readonly IRepository<Me_StCur, Guid> _stcurRepository;
        private readonly IRepository<Dm_Ent, Guid> _entRepository;
        private readonly IRepository<Dm_Client, Guid> _clientRepository;

        public AllotAppService(IRepository<latestAllotModel, Guid> latestAllotRepository, IRepository<latestAllotSUBModel, Guid> latestAllotSubRepository, IRepository<Dm_Warehouser, Guid> warehouserRepository, IRepository<Dm_ItemType, Guid> itemTypeRepository, IRepository<Dm_Item, Guid> itemRepository, IRepository<Dm_Unit, Guid> unitRepository, IRepository<UserModel, Guid> userRepository, IRepository<Dm_Librarylocation, Guid> librarylocationRepository, IRepository<Me_StCur, Guid> stcurRepository, IRepository<Dm_Ent, Guid> entRepository, IRepository<Dm_Client, Guid> clientRepository)
        {
            _latestAllotRepository = latestAllotRepository;
            _latestAllotSubRepository = latestAllotSubRepository;
            _warehouserRepository = warehouserRepository;
            _itemTypeRepository = itemTypeRepository;
            _itemRepository = itemRepository;
            _unitRepository = unitRepository;
            _userRepository = userRepository;
            _librarylocationRepository = librarylocationRepository;
            _stcurRepository = stcurRepository;
            _entRepository = entRepository;
            _clientRepository = clientRepository;
        }


        /// <summary>
        /// 获取库存调拨单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ApiPaging<InventoryTransfer>> GetAllot(AllotInput input)
        {
            var allot = await _latestAllotRepository.GetQueryableAsync();
            var allotSub = await _latestAllotSubRepository.GetQueryableAsync();
            var item = await _itemRepository.GetQueryableAsync();
            var warehouser = await _warehouserRepository.GetQueryableAsync();
            var warehousers = await _warehouserRepository.GetQueryableAsync();
            var user =await _userRepository.GetQueryableAsync();
            
            if (!string.IsNullOrEmpty(input.AllotId))
            {
                allot = allot.Where(x => x.AllotId == input.AllotId);
            }
            if (!string.IsNullOrEmpty(input.DocumentType))
            {
                allot = allot.Where(x => x.DocumentType == input.DocumentType);
            }
            if (input.DataTime != null)
            {
                allot = allot.Where(x => x.PrepareData.Date == input.DataTime);
            }

            var linq = from a in allot
                        join b in allotSub on a.AllotId equals b.AllotId
                        join c in item on b.CommodityId equals c.Itemid
                        join d in warehouser on a.OpenWareHouse equals d.Warehouseid
                        join e in warehousers on a.CloseWareHouse equals e.Warehouseid
                        join f in user on a.Audit equals f.Id.ToString()
                        select new InventoryTransfer
                        {
                           Id=a.Id,
                           AllotId=a.AllotId,
                           DocumentType=a.DocumentType,
                           AllocateGoods=c.Itemname,
                           AllotNumber=b.AllotNumber,
                           TransferType=a.TransferType,
                           Remark =a.Remark,
                           ResponsiblePerson=a.ResponsiblePerson,
                           PreparedBy=a.PreparedBy,
                           PrepareData=a.PrepareData,
                           CloseWareHouse=e.Warehousename,
                           OpenWareHouse=d.Warehousename,
                           ApplicationDate=a.PrepareData,
                           AllotPrice= Convert.ToDecimal(b.AllotNumber) * input.Prices,
                           Auditor =f.TrueName
                        };
            var coie = linq.ToList();
            // 新增：分组合并
            var grouped = linq
                .GroupBy(x => x.Id)
                .Select(g => new InventoryTransfer
                {
                    Id = g.Key,
                    AllotId = g.First().AllotId,
                    DocumentType = g.First().DocumentType,
                    TransferType = g.First().TransferType,
                    Remark = g.First().Remark,
                    ResponsiblePerson = g.First().ResponsiblePerson,
                    PreparedBy = g.First().PreparedBy,
                    PrepareData = g.First().PrepareData,
                    AllocateGoods = string.Join(",", g.Select(x => x.AllocateGoods)), // 拼接Itemname
                    CloseWareHouse = g.First().CloseWareHouse,
                    AllotNumber = g.Sum(x => Convert.ToInt32(x.AllotNumber)).ToString(), // 累加
                    OpenWareHouse = g.First().OpenWareHouse,
                    ApplicationDate = g.First().ApplicationDate,
                    Auditor = g.First().Auditor,
                    AllotPrice = g.Sum(x => x.AllotPrice), // 累加
                });


            var model = grouped.OrderBy(a => a.AllotId)
               .Skip((input.PageIndex - 1) * input.PageSize)
               .Take(input.PageSize)
               .ToList();

            return new ApiPaging<InventoryTransfer>()
            {
                TotalPages= (int)Math.Ceiling(grouped.Count() / (double)input.PageSize),
                Code = ApiEnum.Success,
                Message = "查询成功",
                TotalCount = grouped.Count(),
                PageData = model
            };



        }
        /// <summary>
        /// 添加库存调拨单
        /// </summary>
        /// <returns></returns>
        public async Task<ApiResult<int>> LatestAllot(latestAllotInput input)
        {
            if (input.AllotId==null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "单号为空",
                    Data = 0
                };
            }
            if (input.OpenWareHouse==null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "调出仓库为空",
                    Data = 0
                };
            }
            if (input.CloseWareHouse==null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "调入仓库不能为空",
                    Data = 0
                };
            }
            if (input.OpenWareHouse == input.CloseWareHouse)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "调入仓库和调出仓库不能为空",
                    Data = 0
                };
            }

            foreach(var item in input.LatestSub)
            {
                if (!decimal.TryParse(item.AllotNumber?.ToString(), out decimal number) || number <= 0)
                {
                    return new ApiResult<int>
                    {
                        Code = ApiEnum.Fail,
                        Message = "调拨数量必须大于0",
                        Data = 0
                    };
                }
            }
            var warehouse = await _warehouserRepository.GetQueryableAsync();
            var a = warehouse.Where(x => x.Status == 2 && x.Warehouseid == input.OpenWareHouse && x.Warehouseid==input.CloseWareHouse).FirstOrDefault();

            if (a != null)
            {
                return new ApiResult<int>()
                {
                    Code = ApiEnum.Error,
                    Message = "该仓库暂已锁定",
                    Data = 0
                };
            }


            var latestAllot = ObjectMapper.Map<latestAllotInput, latestAllotModel>(input);

            input.CreationTime = DateTime.Now;
            using (var tran =new TransactionScope())
            {
                try
                {
                    await _latestAllotRepository.InsertAsync(latestAllot);
                    foreach (var item in input.LatestSub)
                    {
                        var sub = ObjectMapper.Map<latestSub, latestAllotSUBModel>(item);
                        sub.AllotId = latestAllot.AllotId;
                        await _latestAllotSubRepository.InsertAsync(sub);
                    }
                    tran .Complete();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("事务失败: " + ex.Message);
                    return new ApiResult<int>()
                    {
                        Code = ApiEnum.Error,
                        Message = "调拨添加失败"
                    };
                }
            }


                return new ApiResult<int>
                {
                    Code = ApiEnum.Success,
                    Message = "调拨添加成功",
                    Data = 0
                };
        }


        /// <summary>
        /// 删除库存调拨单
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> DeleteAllot(string Id)
        {
            var latestAllot=_latestAllotRepository.GetQueryableAsync().Result.Where(x => x.AllotId == Id).FirstOrDefault();
            var latestAllotSub = _latestAllotSubRepository.GetQueryableAsync().Result.Where(x => x.AllotId==latestAllot.AllotId).ToList();

            using (var tran =new TransactionScope())
            {
                try
                {
                    _latestAllotRepository.DeleteAsync(latestAllot);
                    foreach (var item in latestAllotSub)
                    {
                        _latestAllotSubRepository.DeleteAsync(item);
                    }
                }
                catch (Exception ex )
                {
                    Console.WriteLine("事务失败: " + ex.Message);
                    return new ApiResult<int>()
                    {
                        Code = ApiEnum.Error,
                       Message = "事务失败",
                       Data = 0
                    };
                }
            }


            return new ApiResult<int>()
            {
                Code = ApiEnum.Success,
                Message = "删除成功",
                Data = 1
            };


        }



        /// <summary>
        /// 获取库存调拨单查询一条
        /// </summary>
        /// <param name="Allot"></param>
        /// <returns></returns>
        public async Task<ApiResult<ShowAllotOutput>> ShowAllot(string Allot)
        {
            try
            {
                // 获取主表信息
                var allot = await _latestAllotRepository.GetQueryableAsync();
                var allotData = allot.Where(a => a.AllotId == Allot).FirstOrDefault();
                
                if (allotData == null)
                {
                    return new ApiResult<ShowAllotOutput>
                    {
                        Code = ApiEnum.Fail,
                        Message = "未找到该调拨单",
                        Data = null
                    };
                }

                // 获取子表信息
                var allotSub = await _latestAllotSubRepository.GetQueryableAsync();
                var allotSubData = allotSub.Where(a => a.AllotId == Allot).ToList();

                // 获取仓库信息
                var warehouser = await _warehouserRepository.GetQueryableAsync();
                
                // 获取调出仓库名称
                var openWarehouse = warehouser.Where(w => w.Warehouseid == allotData.OpenWareHouse)
                                    .Select(w => w.Warehousename)
                                    .FirstOrDefault() ?? "";

                // 获取调入仓库名称
                var closeWarehouse = warehouser.Where(w => w.Warehouseid == allotData.CloseWareHouse)
                                     .Select(w => w.Warehousename)
                                     .FirstOrDefault() ?? "";

                // 获取商品类型信息
                var itemType = await _itemTypeRepository.GetQueryableAsync();
                
                // 构建子表数据
                var latestSubList = new List<showSub>();
                foreach (var subItem in allotSubData)
                {
                    var itemTypeName = itemType.Where(it => it.Itemtypeid == subItem.CommodityId)
                                     .Select(it => it.Itemtypename)
                                     .FirstOrDefault() ?? "";

                    latestSubList.Add(new showSub
                    {
                        Id = subItem.Id.ToString(),
                        AllotId = subItem.AllotId,
                        CommodityId = subItem.CommodityId,
                        WarehouseId = subItem.WarehouseId,
                        AllotMoney = subItem.AllotMoney,
                        AllotNumber = subItem.AllotNumber,
                        Remark = subItem.Remark
                    });
                }

                // 构建返回数据
                var result = new ShowAllotOutput
                {
                    Id = allotData.Id,
                    AllotId = allotData.AllotId,
                    DocumentType = allotData.DocumentType,
                    TransferType = allotData.TransferType,
                    OpenWareHouse = allotData.OpenWareHouse,
                    CloseWareHouse = allotData.CloseWareHouse,
                    ResponsiblePerson = allotData.ResponsiblePerson,
                    PreparedBy = allotData.PreparedBy,
                    Remark = allotData.Remark,
                    PrepareData = allotData.CreationTime,
                    LatestSub = latestSubList,
                    Audit= allotData.Audit
                };

                return new ApiResult<ShowAllotOutput>
                {
                    Code = ApiEnum.Success,
                    Message = "查询成功",
                    Data = result
                };
            }
            catch (Exception ex)
            {
                return new ApiResult<ShowAllotOutput>
                {
                    Code = ApiEnum.Error,
                    Message = "查询失败：" + ex.Message,
                    Data = null
                };
            }
        }


        /// <summary>
        /// 获取货品
        /// </summary>
        /// <returns></returns>
         public async Task<ApiPaging<ItemOutput>> GetItem()
        {
            var list = await _itemRepository.GetQueryableAsync();
            var itemtype =await _itemTypeRepository.GetQueryableAsync();
            var unit = await _unitRepository.GetQueryableAsync();
            var linq = from a in list
                       join b in itemtype on a.Itemtypeid equals b.Itemtypeid
                       join c in unit on a.Unitid equals c.Unitid
                       select new ItemOutput()
                       {
                           Id=a.Id.ToString(),
                           Itemid = a.Itemid,
                           Itemname = a.Itemname,
                           Satus = a.Satus,
                           Itemtypeid = a.Itemtypeid,
                           Itemspec = a.Itemspec,
                           Unitid = c.Unitname,
                           Entid = a.Entid,
                           Clientid = a.Clientid,
                           Purchaseprice = a.Purchaseprice,
                           Outboundprice = a.Outboundprice,
                           ItmeTypeName = b.Itemtypename
                       };
            return new ApiPaging<ItemOutput>()
            {
                TotalCount = list.Count(),
                TotalPages = (int)Math.Ceiling(list.Count() * 1.0 / 10),
                PageData = linq.ToList()
            };
        }

        /// <summary>
        /// 获取仓库
        /// </summary>s
        /// <returns></returns>
       public async Task<ApiResult<List<GetWareHouseOutput>>> GetWareHouse()
        {
            var items = await _warehouserRepository.GetQueryableAsync();
            var seach = items.ToList();
            return new ApiResult<List<GetWareHouseOutput>>()
            {
                Code = ApiEnum.Success,
                Message = "获取成功",
                Data = ObjectMapper.Map<List<Dm_Warehouser>, List<GetWareHouseOutput>>(seach)
            };
        } 


        /// <summary>
        /// 修改库存调拨单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> UpdateAllot(UpdateAllotInput input)
        {
            if (input.AllotId == null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "单号为空",
                    Data = 0
                };
            }
            if (input.OpenWareHouse == null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "调出仓库为空",
                    Data = 0
                };
            }
            if (input.CloseWareHouse == null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "调入仓库不能为空",
                    Data = 0
                };
            }
            if (input.OpenWareHouse == input.CloseWareHouse)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "调入仓库和调出仓库不能为空",
                    Data = 0
                };
            }

            foreach (var item in input.LatestSub)
            {
                if (!decimal.TryParse(item.AllotNumber?.ToString(), out decimal number) || number <= 0)
                {
                    return new ApiResult<int>
                    {
                        Code = ApiEnum.Fail,
                        Message = "调拨数量必须大于0",
                        Data = 0
                    };
                }
            }

            // 查询主表
            var seach = await _latestAllotRepository.GetQueryableAsync();
            var allotEntity = seach.Where(a => a.AllotId == input.AllotId).FirstOrDefault();
            if (allotEntity == null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "未找到该调拨单",
                    Data = 0
                };
            }

            allotEntity.AllotId = input.AllotId;
            allotEntity.DocumentType = input.DocumentType;
            allotEntity.TransferType = input.TransferType;
            allotEntity.OpenWareHouse = input.OpenWareHouse;
            allotEntity.CloseWareHouse = input.CloseWareHouse;
            allotEntity.ResponsiblePerson = input.ResponsiblePerson;
            allotEntity.PreparedBy = input.PreparedBy;
            allotEntity.PrepareData = input.PrepareData;
            allotEntity.Remark = input.Remark;
            allotEntity.Audit = input.Audit;
            allotEntity.LastModificationTime = DateTime.Now;

            var subList = await _latestAllotSubRepository.GetListAsync(x=>x.AllotId==input.AllotId);
            foreach (var sub in subList)
            {
                await _latestAllotSubRepository.DeleteAsync(sub);
            }
            foreach (var item in input.LatestSub)
            {
                var newsub = new latestAllotSUBModel
                {
                    AllotId = input.AllotId,
                    AllotMoney=item.AllotMoney,
                    AllotNumber=item.AllotNumber,
                    CommodityId=item.CommodityId,
                    WarehouseId=item.WarehouseId,
                    Remark=item.Remark,
                };
                await _latestAllotSubRepository.InsertAsync(newsub);
            }

            await _latestAllotRepository.UpdateAsync(allotEntity);



            return new ApiResult<int>
            {
                Code = ApiEnum.Success,
                Message = "调拨成功",
                Data = 0
            };
        }




        /// <summary>
        /// 通过仓库库位获取商品
        /// </summary>
        /// <param name="warehouseid"></param>
        /// <param name="librarylocationid"></param>
        /// <returns></returns>
        public async Task<ApiPaging<ItemsOutput>> Getitems(GetitemsInput input)
        {
            var list = await _itemRepository.GetQueryableAsync();
            var itemtype = await _itemTypeRepository.GetQueryableAsync();
            var unit = await _unitRepository.GetQueryableAsync();
            var warehouse = await _warehouserRepository.GetQueryableAsync();
            var librarylocation = await _librarylocationRepository.GetQueryableAsync();
            var stsur =await _stcurRepository.GetQueryableAsync();
            var end = await _entRepository.GetQueryableAsync();
            var client = await _clientRepository.GetQueryableAsync();

            if (!string.IsNullOrEmpty(input.warehouseid))
            {
                stsur = stsur.Where(a => a.Warehouseid == input.warehouseid);
            }
            if (!string.IsNullOrEmpty(input.librarylocationid))
            {
                stsur = stsur.Where(a => a.Librarylocationid == input.librarylocationid);
            }




            var linq =from a in stsur
                      join b in list on a.Itemid equals b.Itemid
                      join c in itemtype on b.Itemtypeid equals c.Itemtypeid
                      join d in unit on b.Unitid equals d.Unitid
                      join f in warehouse on a.Warehouseid equals f.Warehouseid
                      join g in librarylocation on a.Librarylocationid equals g.Librarylocationid
                      join h in end on b.Entid equals h.Entid
                      join i in client on b.Clientid equals i.Clientid
                      select new ItemsOutput
                      {
                          Id = b.Id.ToString(),
                          Itemid = a.Itemid,
                          Clientid =i.Clientname,
                          Satus=b.Satus,
                          Entid=h.Entname,
                          Itemname=b.Itemname,
                          Itemspec=b.Itemspec,
                          Itemtypeid=c.Itemtypename,
                          Librarylocationid=g.Librarylocationname,
                          Outboundprice=b.Outboundprice,
                          Purchaseprice=b.Purchaseprice,
                          Unitid=d.Unitname,
                          Warehouseid=f.Warehousename
                      };

            return new ApiPaging<ItemsOutput>
            {
                TotalCount = linq.Count(),
                TotalPages = 1,
                PageData = linq.ToList()
            };


        }



        /// <summary>
        /// 审批调拨
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> Approve(ApproveInput input)
        {
            var allot =await _latestAllotRepository.FirstOrDefaultAsync(x=>x.AllotId==input.AllotId);
            if (allot == null)
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "未找到该调拨单",
                    Data = 0
                };
            }

            if(allot.DocumentType=="通过" || allot.DocumentType == "已完成")
            {
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Message = "该调拨单已处理",
                    Data = 0
                };
            }

            
            allot.DocumentType = input.DocumentType;


            await _latestAllotRepository.UpdateAsync(allot);
            return new ApiResult<int>
            {
                Code = ApiEnum.Success,
                Message = "处理成功",
                Data = 0
            };
        }








    }
}
